/**
 * \file 3d.h
 * 3D Graphics Materials
 *
 * Provides the following:
 *	- Materials
 **
 * Authors: Sean Micklethwaite
 * License... etc.
 **/

#ifndef __3d_materialH__
#define __3d_materialH__

#include "3d.h"
#include "glsl.h"

namespace WtfGraphics {
	/**
	 * The basic material class.
	 **/
	class Material : public WtfEngine::DataObject {
	protected:
		fVector4D	mvDiffuse;
		fVector3D	mvSpecular, mvEmissive;
		float		mfPower;
		WtfEngine::GLSLProgram::tRef mrShader;

	public:
		typedef struct MaterialCreationOptions {
			fVector4D	vDiffuse;
			fVector3D	vSpecular, vEmissive;
			float		fPower;

			MaterialCreationOptions();
		} tCreationOptions;

		Material(const WtfEngine::StringPool::Entry& sName);
		Material(const WtfEngine::StringPool::Entry& sName, const tCreationOptions& opts);

		virtual void Activate();
		virtual void Deactivate();

		DATA_RECONSTRUCTIBLE(Material, GC_ADDEDSIZE_AUTO(WtfEngine::DataObject, Material));
	};

	class MaterialBinding: public GraphicsData {
		Material::tCacheRef     mrMaterial;
		GraphicsData::tCacheRef mrGraphics;

	public:
		MaterialBinding(const WtfEngine::String& sName, const Material::tCacheRef& rMaterial, const GraphicsData::tCacheRef& rGfx);

		virtual void render();

		inline const Material::tCacheRef& getMaterial() const {
			return mrMaterial;
		};
		inline const GraphicsData::tCacheRef& getGraphics() const {
			return mrGraphics;
		};

		DATA_RECONSTRUCTIBLE(MaterialBinding, GC_ADDEDSIZE_AUTO(GraphicsData, MaterialBinding));
	};

	class DiffuseTextureMaterial: public Material {
		protected:
			WtfEngine::Texture::tCacheRef mrTexture;

		public:
			typedef struct DiffuseTextureMaterialCreationOptions: public MaterialCreationOptions {
				WtfEngine::Texture::tCacheRef rTexture;

				DiffuseTextureMaterialCreationOptions(const WtfEngine::Texture::tCacheRef& rTex)
					: rTexture(rTex) {};
			} tCreationOptions;

			DiffuseTextureMaterial(const WtfEngine::StringPool::Entry& sName);
			DiffuseTextureMaterial(const WtfEngine::StringPool::Entry& sName, const tCreationOptions& opts);

			virtual void Activate();
			virtual void Deactivate();

			inline WtfEngine::Texture::tCacheRef getDiffuseMap() const {
				return mrTexture;
			};

			DATA_RECONSTRUCTIBLE(DiffuseTextureMaterial, GC_ADDEDSIZE_AUTO(Material, DiffuseTextureMaterial));
	};


	/**
	 * Loads a texture image with default colour and blending attributes.
	 **/
	class DefaultDiffuseTextureMaterial: public DiffuseTextureMaterial {
	public:
		DefaultDiffuseTextureMaterial(const WtfEngine::StringPool::Entry& sName)
			: DiffuseTextureMaterial(sName) {};

		static WtfEngine::IDataObject * Load(const WtfEngine::StringPool::Entry& sName);

		DATA_LOADABLE(DefaultDiffuseTextureMaterial,
			GC_ADDEDSIZE_AUTO(DiffuseTextureMaterial, DefaultDiffuseTextureMaterial));
	};
};

#endif
